package com.qianfeng.smartdevice.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qianfeng.smartdevice.cache.CategoryCache;
import com.qianfeng.smartdevice.enums.CheckType;
import com.qianfeng.smartdevice.events.CategoryCacheChangeEvent;
import com.qianfeng.smartdevice.exceptions.AddDataErrorException;
import com.qianfeng.smartdevice.exceptions.DeleteDataErrorException;
import com.qianfeng.smartdevice.exceptions.MyErrorCode;
import com.qianfeng.smartdevice.exceptions.UpdateDataErrorException;
import com.qianfeng.smartdevice.mapper.SysCategoryMapper;
import com.qianfeng.smartdevice.pojo.SysCategory;
import com.qianfeng.smartdevice.pojo.SysUserInfo;
import com.qianfeng.smartdevice.service.SysCategoryService;
import com.qianfeng.smartdevice.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @time: 2022-03-17 15:05
 */
@Service
@Transactional
public class SysCategoryServiceImpl implements SysCategoryService {

    private ApplicationContext applicationContext;
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private CategoryCache categoryCache;
    @Autowired
    public void setCategoryCache(CategoryCache categoryCache) {
        this.categoryCache = categoryCache;
    }

    private SysCategoryMapper sysCategoryMapper;
    @Autowired
    public void setSysCategoryMapper(SysCategoryMapper sysCategoryMapper) {
        this.sysCategoryMapper = sysCategoryMapper;
    }

    @Override
    public void addSysCategory(SysCategory sysCserrtegory) {
        //检查数据是不是传递了
        Assert.isTrue(!sysCserrtegory.isEmpty(CheckType.ADD),()->{
            throw new AddDataErrorException("分类名称没有传递", MyErrorCode.DATA_NULL);
        });
        //检查当前是不是登录了用户,如何判断用户登录了, 所以一定有个地方保存了登录的用户(数据到底保存在什么地方是我们决定的),我们登录完成后放到session了
        //那我们只需要从session中获取
        SysUserInfo userInfo = SecurityUtils.getLoginUser();
        //我们要求必须登录
        Assert.notNull(userInfo,()->{
            throw new AddDataErrorException("未登陆", MyErrorCode.NOT_LOGIN);
        });
        //补充数据
        sysCserrtegory.setCreateBy(userInfo.getUsername());
        sysCserrtegory.setCreateTime(new Date());
        sysCategoryMapper.addSysCategory(sysCserrtegory);
        //通知缓存更新
        applicationContext.publishEvent(new CategoryCacheChangeEvent());

    }

    @Override
    @Transactional(readOnly = true)
    public SysCategory findById(Long id) {
        //注意,按照我们的要求,id必须大于0
        //从缓存中查询
        SysCategory sysCategory = categoryCache.get(id);
        return sysCategory;
//        return sysCategoryMapper.findById(id);
    }

    @Override
    public PageInfo<SysCategory> findByPage(int pageNum, int pageSize, String categoryName) {
        PageHelper.startPage(pageNum, pageSize);
        //先用条件过滤到一部分数据, 然后以剩下的数据做分页
        //SELECT * FROM XXX WHERE XXXX LIKE %ASDAD% LIMIT 1,1
        List<SysCategory> categoryList = categoryCache.getCategoryListCache();

//        ArrayList<Object> arrayList = new ArrayList<>();//保存有符合过滤条件的数据
//        for (SysCategory sysCategory : categoryList) {
//            if (!StringUtils.hasText(categoryName)||sysCategory.getCategoryName().contains(categoryName)) {//包含指定条件的数据保存起来
//                arrayList.add(sysCategory);
//            }
//        }
        //拿到所有和关键字匹配的数据
        List<SysCategory> categories = categoryList.stream().filter(sysCategory -> {
            //如果传值了就代表判断数据是否包含,如果没有,就直接返回true就是所有的数据都要
            return StringUtils.hasText(categoryName) ? sysCategory.getCategoryName().contains(categoryName) : true;
        }).collect(Collectors.toList());

        //这是当前页要的数据,这个数据要从符合过滤条件中的数据来拿
        List<SysCategory> realList = categories.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
        //将数据保存到pageinfo中
        PageInfo<SysCategory> pageInfo = new PageInfo<>(realList);
        pageInfo.setTotal(categories.size());//设置的是符合条件的所有的数据
        pageInfo.setPageSize(pageSize);
        pageInfo.setPageNum(pageNum);

        return pageInfo;
    }

    @Override
    public int updateCategory(SysCategory category) {
        //如果什么都不传递, 是不能执行更新操作的,需要对数据进行校验
        Assert.isTrue(!category.isEmpty(CheckType.UPDATE),()->{
            throw new UpdateDataErrorException("数据为空", MyErrorCode.DATA_NULL);
        });

        //必须登录
        //检查当前是不是登录了用户,如何判断用户登录了, 所以一定有个地方保存了登录的用户(数据到底保存在什么地方是我们决定的),我们登录完成后放到session了
        //那我们只需要从session中获取
        SysUserInfo userInfo = SecurityUtils.getLoginUser();
        //我们要求必须登录
        Assert.notNull(userInfo,()->{
            throw new AddDataErrorException("未登陆", MyErrorCode.NOT_LOGIN);
        });
        //设置其他数据
        category.setUpdateTime(new Date());
        category.setUpdateBy(userInfo.getUsername());
        int result = sysCategoryMapper.updateCategory(category);

        //发布一个事件
        applicationContext.publishEvent(new CategoryCacheChangeEvent());
        return result;
    }

    @Override
    public int deleteByIds(List<Long> ids) {

        Assert.notEmpty(ids,()->{
            throw new DeleteDataErrorException("未传递主键", MyErrorCode.DATA_NULL);
        });
        SysUserInfo userInfo = SecurityUtils.getLoginUser();
        //我们要求必须登录
        Assert.notNull(userInfo,()->{
            throw new AddDataErrorException("未登陆", MyErrorCode.NOT_LOGIN);
        });
        int count = sysCategoryMapper.deleteByIds(ids);//返回结果是删除成功多少条
        //发布一个事件,更新缓存
        applicationContext.publishEvent(new CategoryCacheChangeEvent());
        return count;
    }


}
